package com.dchh.android.suverynew.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.util.TypeUtils;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.nio.charset.Charset;

import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;

/**
 * Created by qbcby on 2016/7/6.
 */
public class FastJsonConverterFactory extends Converter.Factory {
    public static Converter.Factory create() {
        return new FastJsonConverterFactory();
    }

    private FastJsonConverterFactory() {
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        return new ResponseBodyConverter<>(type);
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return new RequestBodyConverter<>(type);
    }

    private static class ResponseBodyConverter<T> implements Converter<ResponseBody, T> {
        private final Type type;

        public ResponseBodyConverter(Type type) {
            this.type = type;
        }

        @Override
        public T convert(ResponseBody value) throws IOException {
            final byte[] bytes;
            try {
                bytes = value.bytes();
            } finally {
                value.close();
            }
            Object obj = JSON.parse(bytes);
            final JSONObject jsonObject;
            if (obj instanceof JSONObject && (jsonObject = (JSONObject) obj).containsKey("return_code")) {
                final ResponseResult responseResult = JSON.toJavaObject(jsonObject, ResponseResult.class);
                responseResult.checkIsSuccess();
                return TypeUtils.cast(responseResult.getData(), type, ParserConfig.getGlobalInstance());
            } else if (obj instanceof JSON) {
                return TypeUtils.cast(obj, type, ParserConfig.getGlobalInstance());
            }
            throw new IOException("responseBody is not Json!");
        }
    }

    private static class RequestBodyConverter<T> implements Converter<T, RequestBody> {
        private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
        private static final Charset UTF_8 = Charset.forName("UTF-8");
        private final Type type;

        public RequestBodyConverter(Type type) {
            this.type = type;
        }

        @Override
        public RequestBody convert(T value) throws IOException {
            return RequestBody.create(MEDIA_TYPE, JSON.toJSONBytes(value, new SerializerFeature[0]));
        }
    }
}
